package com.sise.rsc.schedule;


import com.sise.rsc.dao.RedisDao;
import com.sise.rsc.entity.APackage;
import com.sise.rsc.repository.APackageRepository;
import com.sise.rsc.service.PackageService;
import com.sise.rsc.service.TaskService;
import com.sise.rsc.util.CacheUtil;
import com.sise.rsc.websocket.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.Schedules;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;


import java.io.IOException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 *  定时任务配置
 */
@Slf4j
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {

    /** 线程池线程数量 */
    private static final int THREAD_COUNT = 1;

    @Autowired
    private RedisDao redisDao;
    @Autowired
    private PackageService packageService;

    @Autowired
    private TaskService taskService;

    /**
     * 过期的订单信息处理, 每10秒钟执行一次
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void clearShareCache() throws IOException {
        if (WebSocketService.clients.get("002")!=null){
            WebSocketService.clients.get("002").getSession().getBasicRemote().sendText("服务器端发来的消息啦：你好啊002");
        }

        //System.out.println("执行一次查找操作");
        for (String s : CacheUtil.packageList) {
            if (redisDao.getStringByKey(s) != null)continue;
            else {
                //过期,删除key,更改等待状态-1
                CacheUtil.packageList.remove(s);
                redisDao.setKey(s,"00",1L, TimeUnit.SECONDS);
                packageService.updateAPackageStateByNo(-1,s.substring(s.indexOf(':')+1));
                System.out.println("订单：" + s+" 已经自动取消");

            }

        }
    }

    /**
     * 处理前一天未分配的包裹,8:30自动分配
     *
     */
    @Scheduled(cron = "0 30 8 * * ?")
    public void task(){

        //处理前天未按排取件任务的订单
        for (String pNo : CacheUtil.packageNextDayList) {
            APackage pa = packageService.findAPackageByNo(pNo);
            if (pa!=null){
                //分配任务：
                if (taskService.AssignTasks(pa,"取件")){
                    //成功
                    CacheUtil.packageNextDayList.remove(pNo);
                    System.out.println("package:" + pNo+" 成功分配取件快递员");
                }else {
                    //失败
                    CacheUtil.packageNextDayList.remove(pNo);
                    //判断是否为可自动分配
                    if (taskService.isCanAutoAssignTasks(pa.getSendAddress())){

                        CacheUtil.packageAutoList.add(pNo);
                    }
                }

            }
        }

        //处理前天未按排派件任务的订单
        for (String pNo : CacheUtil.packageDeliverNextDayList) {
            APackage pa = packageService.findAPackageByNo(pNo);
            if (pa!=null){
                //分配任务：
                if (taskService.AssignTasks(pa,"派件")){
                    //成功
                    CacheUtil.packageDeliverNextDayList.remove(pNo);
                    System.out.println("package:" + pNo+" 成功分配派件快递员");
                }else {
                    //失败
                    CacheUtil.packageDeliverNextDayList.remove(pNo);
                    //判断是否为可自动分配
                    if (taskService.isCanAutoAssignTasks(pa.getReceiptAddress())){

                        CacheUtil.packageDeliverAutoList.add(pNo);
                    }
                }

            }
        }

    }
    /**
     * 线程配置, 让多个定时任务在同一个线程池的不同线程中并发执行
     *
     * @param scheduledTaskRegistrar
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        // 手动创建线程, 可以规避资源耗尽, 且可以设置线程名称规则
        ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor( THREAD_COUNT, new BasicThreadFactory.Builder().namingPattern("Schedule-Thread-Pool-Thread%d").daemon(true).build() );
        scheduledTaskRegistrar.setScheduler(scheduledExecutorService);
    }
}